package net.risesoft.risebi.collection.web.login;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.risesoft.risebi.collection.commons.constants.SystemConstants;
import net.risesoft.risebi.collection.commons.memcached.MemCachedService;
import net.risesoft.risebi.collection.event.eventobj.EventObject;
import net.risesoft.risebi.collection.event.eventobj.SystemLogEventObj;
import net.risesoft.risebi.collection.mail.Mail;
import net.risesoft.risebi.collection.mail.MailService;
import net.risesoft.risebi.collection.model.Application;
import net.risesoft.risebi.collection.model.Department;
import net.risesoft.risebi.collection.model.Employee;
import net.risesoft.risebi.collection.model.Service;
import net.risesoft.risebi.collection.model.SystemLog;
import net.risesoft.risebi.collection.model.User;
import net.risesoft.risebi.collection.service.ApplicationManager;
import net.risesoft.risebi.collection.service.PrivilegeManager;
import net.risesoft.risebi.collection.service.ServiceManager;
import net.risesoft.risebi.collection.service.UserManager;
import net.risesoft.risebi.collection.web.BaseAction;
import net.risesoft.risebi.commons.struts2extension.Trimable;
import net.risesoft.risebi.commons.util.ContextUtil;
import net.risesoft.risebi.commons.util.ExceptionUtil;
import net.risesoft.risebi.commons.util.GUID;
import net.risesoft.risebi.commons.util.PropsUtil;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.LazyDynaBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.web.util.WebUtils;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;

/**
 * 用户的登录登出action
 */
@Namespace("/login/LoginAction")
public class LoginAction extends BaseAction implements Trimable{	
	private static final long serialVersionUID = -1353599771551590602L;
	private final Log log = LogFactory.getLog(LoginAction.class);
	
	private String username;
	private String password;
	private String email;
	private String captcha; //验证码
	
	private UserManager userManager;
	private MailService mailService;
	private PrivilegeManager privilegeManager;
	private ServiceManager serviceManager;
	private ApplicationManager applicationManager;
	private MemCachedService memCachedService;
	
	@Action(value="prepareForgetPassword",
			results={@Result(name="success", location="/login/forgetPassword.jsp")}
	)
    public String prepareForgetPassword() throws Exception {
        return SUCCESS;
    }

	@Action(value="sendMail")
    public String sendMail() throws Exception {
    	LazyDynaBean ldb = new  LazyDynaBean();
    	
    	try {
    		User user = userManager.getUserByName(username);  
        	if(user==null){
        		ldb.set("success", false);    			
       			ldb.set("reason", "1"); //该用户不存在
        	}else{
        		String regEmail = user.getEmail();
        		if(regEmail==null){
        			ldb.set("success", false);    			
           			ldb.set("reason", "2"); //该用户没有注册邮件地址
        		}else{
        			if(!email.equalsIgnoreCase(regEmail)){
            			ldb.set("success", false);    			
               			ldb.set("reason", "3"); //邮件地址与该用户注册时提供的邮件地址不符
            		}else{
            			Mail mail = new Mail();
            			mail.setSubject("您的密码");
            			mail.setContent("您的密码：" + user.getPassword());
            			
            			String fromAddress = PropsUtil.getProperty("defaultMailAddress");
            			
            			String fromUserName = null;
            			int iPos = fromAddress.indexOf("@");
            			fromUserName = fromAddress.substring(0, iPos);
            			
            			mail.setFromAddress(fromAddress);
            			mail.setFromUserName(fromUserName);
            			List<String> toAddresses = new ArrayList<String>();
            			toAddresses.add(user.getEmail());
            			mail.setToAddresses(toAddresses);
            			
            			mailService.sendMail(mail);
    	        		
    	        		ldb.set("success", true);
    	    			ldb.set("reason", "4"); //密码已发送到您的邮箱
            		}
        		}        		
        	}
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		return AJAX;
    }
	
	@Action(value="prepareLogin",
			results={@Result(name="success", location="/login/login.jsp")}
	)
    public String prepareLogin() throws Exception {
        return SUCCESS;
    }
	
	@Action(value="logon")
    public String logon() throws Exception {
    	LazyDynaBean ldb = new  LazyDynaBean();
    	
     	HttpServletRequest request = ServletActionContext.getRequest();
    	HttpServletResponse response = ServletActionContext.getResponse();
    	
    	try {
    		if(log.isDebugEnabled()){
    			log.debug("用户："+username+"开始登录系统，验证中......");
    		}
    		
//    		有可能用户的图片还暂时没有显示的时候，用户就直接点击‘登录’
    		String answer = request.getParameter("captcha");
    		if(answer==null||answer.equals("")){
    			ldb.set("success", false);
    			ldb.set("reason", "请您填写验证码");
    			this.json = JSONObject.fromObject(ldb).toString();
    			return AJAX;
    		}
    		
//    		判断是否集群，假如集群则从memcache中获得
    		if(SystemConstants.REPORT_CLUSTERED){
    			Cookie c = WebUtils.getCookie(request, "riseSessionId");
    			if(c==null){
//    				到这个时候了，c不应该是空的，因为有了验证码
    			}
    			String vKey = c.getValue() + "v";
    			String validateCode = (String) memCachedService.getMemCachedValue(vKey);
    			if(!validateCode.equalsIgnoreCase(answer)) {
        			ldb.set("success", false);
        			ldb.set("reason", "验证码不正确！");
        			this.json = JSONObject.fromObject(ldb).toString();
        			return AJAX;
        		}
    		}else{
    			String validateCode = (String)request.getSession().getAttribute("validateCode");
    			if(validateCode==null){
    				ldb.set("success", false);
        			ldb.set("reason", "请重新点击一下验证码图片来填写最新的验证码。");
        			this.json = JSONObject.fromObject(ldb).toString();
        			return AJAX;
    			}
    			
        		answer = request.getParameter("captcha");
        		if(!validateCode.equalsIgnoreCase(answer)) {
        			ldb.set("success", false);
        			ldb.set("reason", "验证码不正确！");
        			this.json = JSONObject.fromObject(ldb).toString();
        			return AJAX;
        		}
    		}
    		
    		User user = userManager.getUserByNameAndPassword(username, password);  
        	if(user!=null){
        		int userType = user.getUserType();
        		userType = (userType==0?User.USERTYPE_ENTERPRISEUSER:userType);
        		if(userType!=User.USERTYPE_SYSTEMMANAGER){
        			ldb.set("success", false);
        			ldb.set("reason", "对不起，没有经过授权，不允许访问。");
        			this.json = JSONObject.fromObject(ldb).toString();
        			return AJAX;
        		}
        		
        		if(log.isDebugEnabled()){
        			log.debug("用户："+username+"已经通过验证，开始组成权限属性.....");
        		}
  
//        		组成user的roles数组
        		String roles = privilegeManager.getUserRoles(user.getGuid());
        		if(roles==null||roles.equals("")){
        			user.setRoles(new String[0]);
        		}else{
        			String[] roleArray = roles.split(",");
                	user.setRoles(roleArray);
        		}
        			
//        		组成user的departments数组 以及 当前服务和应用
        		List<String> departmentList = new ArrayList<String>();
    			Employee e = user.getEmployee();
    			Department d = e.getDepartment();
    			if(d!=null){
    				departmentList.add(d.getGuid());
        			while(d.getParentDepartment()!=null){
        				departmentList.add(d.getParentDepartment().getGuid());
        				d = d.getParentDepartment();
        			}
    			}
    			
    			String[] departments = new String[departmentList.size()];
        		for(int i=0;i<departmentList.size();i++){
        			departments[i] = departmentList.get(i);
        		}
        		user.setDepartments(departments);
        		
//            		当前服务
        		List<Service> services = serviceManager.getServicesWithPermission(user);
        		if(services!=null&&services.size()==1){
        			Service service = services.get(0);
        			user.setDefaultService(service);
        			
        			List<Application> apps = applicationManager.getAppsByServiceWithPermission(service.getGuid(), user);
        			if(apps!=null&&apps.size()==1){
        				Application app = apps.get(0);
        				user.setDefaultApp(app);
        			}
        		}
        		
//        		判断一下用户是否是超级用户
        		user.isSuperAdmin();
        		
//        		设置用户访问的IP
        		String ip = request.getRemoteAddr();
        		user.setIp(ip);

        		if(SystemConstants.REPORT_CLUSTERED){
//            		假如是集群，首先设置Cookie，然后存入memcached中2个值，一个是riseSessionId+c，有效时间2个小时
//        			一个是riseSessionId+u，有效时间为12个小时
        			Cookie c = WebUtils.getCookie(request, "riseSessionId");
        			if(c==null){
        				String riseSessionId = new GUID().toString();
        				c = new Cookie("riseSessionId" , riseSessionId);
        				String contextPath = request.getContextPath();
        				if(contextPath.equals("")){
        					contextPath = "/";
        				}
        				c.setPath(contextPath);
        				response.addCookie(c);
        			}
        			String cKey = c.getValue() + "c";
        			memCachedService.setMemCachedValue(cKey, 1);
        			
        			String uKey = c.getValue() + "u";
        			Date expiry = new Date(12 * 60 * 60 * 1000);
        			memCachedService.setMemCachedValue(uKey, user, expiry);
        		}else{
//            		放入session中
            		ActionContext.getContext().getSession().put(PropsUtil.getProperty(SystemConstants.REPORT_USER), user);
        		}
        		
        		log.info("用户:"+username+"，IP："+ip+"，通过权限认证，已经登录系统。");
        		
//        		记录日志
        		SystemLog systemLog = new SystemLog();
        		systemLog.setOpterateType(SystemLog.OPTERATETYPE_LOGON);
        		systemLog.setUser(user);
        		EventObject systemLogEventObject = new SystemLogEventObj(this);
        		Map systemLogMap = new HashMap();
        		systemLogMap.put("systemLog", systemLog);
        		systemLogMap.put("keyName", "login");
        		systemLogEventObject.setDataMap(systemLogMap);
        		ContextUtil.getAc().publishEvent(systemLogEventObject);

        		ldb.set("success", true);
    			ldb.set("reason", "登录成功！");
        	}else{
        		ldb.set("success", false);    			
        		int count = userManager.getCount("select count(*) from User u where u.name='" + username + "'");
        		if(count==0){
        			ldb.set("reason", "错误的用户名！");
        		}else{
        			ldb.set("reason", "错误的口令！");
        		}
        	}
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		return AJAX;
    }
    
    @Action(value="logon4sso")
    public String logon4sso() throws Exception {
        LazyDynaBean ldb = new  LazyDynaBean();
        
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        
        try {
            User user = userManager.getUserByName(username);
            if(user!=null){
                int userType = user.getUserType();
                userType = (userType==0?User.USERTYPE_ENTERPRISEUSER:userType);
                if(userType!=User.USERTYPE_SYSTEMMANAGER){
                    ldb.set("success", false);
                    ldb.set("reason", "对不起，没有经过授权，不允许访问。");
                    this.json = JSONObject.fromObject(ldb).toString();
                    return AJAX;
                }
                
//              组成user的roles数组
                String roles = privilegeManager.getUserRoles(user.getGuid());
                if(roles==null||roles.equals("")){
                    user.setRoles(new String[0]);
                }else{
                    String[] roleArray = roles.split(",");
                    user.setRoles(roleArray);
                }
                    
//              组成user的departments数组 以及 当前服务和应用
                List<String> departmentList = new ArrayList<String>();
                Employee e = user.getEmployee();
                Department d = e.getDepartment();
                if(d!=null){
                    departmentList.add(d.getGuid());
                    while(d.getParentDepartment()!=null){
                        departmentList.add(d.getParentDepartment().getGuid());
                        d = d.getParentDepartment();
                    }
                }
                
                String[] departments = new String[departmentList.size()];
                for(int i=0;i<departmentList.size();i++){
                    departments[i] = departmentList.get(i);
                }
                user.setDepartments(departments);
                
//                  当前服务
                List<Service> services = serviceManager.getServicesWithPermission(user);
                if(services!=null&&services.size()==1){
                    Service service = services.get(0);
                    user.setDefaultService(service);
                    
                    List<Application> apps = applicationManager.getAppsByServiceWithPermission(service.getGuid(), user);
                    if(apps!=null&&apps.size()==1){
                        Application app = apps.get(0);
                        user.setDefaultApp(app);
                    }
                }
                
//              判断一下用户是否是超级用户
                user.isSuperAdmin();
                
//              设置用户访问的IP
                String ip = request.getRemoteAddr();
                user.setIp(ip);

                if(SystemConstants.REPORT_CLUSTERED){
//                  假如是集群，首先设置Cookie，然后存入memcached中2个值，一个是riseSessionId+c，有效时间2个小时
//                  一个是riseSessionId+u，有效时间为12个小时
                    Cookie c = WebUtils.getCookie(request, "riseSessionId");
                    if(c==null){
                        String riseSessionId = new GUID().toString();
                        c = new Cookie("riseSessionId" , riseSessionId);
                        String contextPath = request.getContextPath();
                        if(contextPath.equals("")){
                            contextPath = "/";
                        }
                        c.setPath(contextPath);
                        response.addCookie(c);
                    }
                    String cKey = c.getValue() + "c";
                    memCachedService.setMemCachedValue(cKey, 1);
                    
                    String uKey = c.getValue() + "u";
                    Date expiry = new Date(12 * 60 * 60 * 1000);
                    memCachedService.setMemCachedValue(uKey, user, expiry);
                }else{
//                  放入session中
                    ActionContext.getContext().getSession().put(PropsUtil.getProperty(SystemConstants.REPORT_USER), user);
                }
                
//              记录日志
                SystemLog systemLog = new SystemLog();
                systemLog.setOpterateType(SystemLog.OPTERATETYPE_LOGON);
                systemLog.setUser(user);
                EventObject systemLogEventObject = new SystemLogEventObj(this);
                Map systemLogMap = new HashMap();
                systemLogMap.put("systemLog", systemLog);
                systemLogMap.put("keyName", "login");
                systemLogEventObject.setDataMap(systemLogMap);
                ContextUtil.getAc().publishEvent(systemLogEventObject);

                ldb.set("success", true);
                ldb.set("reason", "登录成功！");
            }else{
                ldb.set("success", false);              
                int count = userManager.getCount("select count(*) from User u where u.name='" + username + "'");
                if(count==0){
                    ldb.set("reason", "错误的用户名！");
                }else{
                    ldb.set("reason", "错误的口令！");
                }
            }
        } catch (Exception e) {
            ldb.set("success", false);
            ldb.set("reason", e.getMessage());
        }
        
        this.json = JSONObject.fromObject(ldb).toString();
        return AJAX;
    }

	@Action(value="logout",
			results={@Result(name="success", location="/login/login.jsp")}
	)
    public String logout() throws Exception {
    	try {
    		User user = getSessionUser();
    		if(user==null)
    			return SUCCESS;
    		
    		HttpServletRequest request = ServletActionContext.getRequest();
    		
    		if(SystemConstants.REPORT_CLUSTERED){
//        		清除memcached中的内容
        		Cookie c = WebUtils.getCookie(request, "riseSessionId");
    			if(c!=null){
    				String cKey = c.getValue() + "c";
    				memCachedService.delete(cKey);
    				
    				String uKey = c.getValue() + "u";
    				memCachedService.delete(uKey);
    			}
    		}else{
    			ActionContext.getContext().getSession().clear();
        		request.getSession().invalidate();
    		}
    		
    		log.info("用户: "+user.getName()+" 登出系统。");
    		
//    		String ip = request.getRemoteAddr();
    		
//    		记录日志
    		SystemLog systemLog = new SystemLog();
    		systemLog.setOpterateType(SystemLog.OPTERATETYPE_LOGOUT);
    		systemLog.setUser(user);
    		EventObject systemLogEventObject = new SystemLogEventObj(this);
    		Map systemLogMap = new HashMap();
    		systemLogMap.put("systemLog", systemLog);
    		systemLogMap.put("keyName", "logout");
    		systemLogEventObject.setDataMap(systemLogMap);
    		ContextUtil.getAc().publishEvent(systemLogEventObject);
		} catch (Exception e) {
			log.error(ExceptionUtil.transformException(e));
		}
		
		return SUCCESS;
    }

    @Action(value="logout4sso",
            results={@Result(name="success", location="/login/logout4sso.jsp")}
    )
    public String logout4sso() throws Exception {
        try {
            User user = getSessionUser();
            if(user==null)
                return SUCCESS;
            
            HttpServletRequest request = ServletActionContext.getRequest();
            
            if(SystemConstants.REPORT_CLUSTERED){
//                      清除memcached中的内容
                Cookie c = WebUtils.getCookie(request, "riseSessionId");
                if(c!=null){
                    String cKey = c.getValue() + "c";
                    memCachedService.delete(cKey);
                    
                    String uKey = c.getValue() + "u";
                    memCachedService.delete(uKey);
                }
            }else{
                ActionContext.getContext().getSession().clear();
                this.getSession().invalidate();
            }
            
            log.info("用户: "+user.getName()+" 登出系统。");
            
//                  String ip = request.getRemoteAddr();
            
//                  记录日志
            SystemLog systemLog = new SystemLog();
            systemLog.setOpterateType(SystemLog.OPTERATETYPE_LOGOUT);
            systemLog.setUser(user);
            EventObject systemLogEventObject = new SystemLogEventObj(this);
            Map systemLogMap = new HashMap();
            systemLogMap.put("systemLog", systemLog);
            systemLogMap.put("keyName", "logout");
            systemLogEventObject.setDataMap(systemLogMap);
            ContextUtil.getAc().publishEvent(systemLogEventObject);
        } catch (Exception e) {
            log.error(ExceptionUtil.transformException(e));
        }
        
        return SUCCESS;
    }

    /* (non-Javadoc)
	 * @see net.risesoft.commons.struts2extension.Trimable#afterTrim(com.opensymphony.xwork2.ActionInvocation)
	 */
	public void afterTrim(ActionInvocation invocation) {		
	}

	/* (non-Javadoc)
	 * @see net.risesoft.commons.struts2extension.Trimable#preTrim(com.opensymphony.xwork2.ActionInvocation)
	 */
	public boolean preTrim(ActionInvocation invocation) {
		return true;
	}
	
	public void setMemCachedService(MemCachedService memCachedService) {
		this.memCachedService = memCachedService;
	}

	public void setServiceManager(ServiceManager serviceManager) {
		this.serviceManager = serviceManager;
	}

	public void setApplicationManager(ApplicationManager applicationManager) {
		this.applicationManager = applicationManager;
	}

	public void setPrivilegeManager(PrivilegeManager privilegeManager) {
		this.privilegeManager = privilegeManager;
	}

	public void setUserManager(UserManager userManager) {
		this.userManager = userManager;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setCaptcha(String captcha) {
		this.captcha = captcha;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public void setMailService(MailService mailService) {
		this.mailService = mailService;
	}
	
}